package com.sntk.organauthomanager.query;

import com.sntk.organauthomanager.application.dto.OperatorInfo;
import com.sntk.organauthomanager.application.dto.PageData;
import com.sntk.organauthomanager.application.dto.UserDTO;
import com.sntk.organauthomanager.application.dto.UserVO;
import com.sntk.organauthomanager.application.mapper.UserMapper;
import com.sntk.organauthomanager.infrastructure.commit.impl.MedicalUserCommitConvert;
import com.sntk.organauthomanager.infrastructure.db.entity.OrganizationEntity;
import com.sntk.organauthomanager.infrastructure.db.entity.UserEntity;
import com.sntk.organauthomanager.infrastructure.db.repository.OrganizationDBRepository;
import com.sntk.organauthomanager.infrastructure.db.repository.UserDBRepository;
import com.sntk.organauthomanager.query.param.UserCondition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: UserQuery
 * @author: wgchao
 * @createTime: 2020/7/21 9:20 AM
 * @Description: TODO
 */
@Service
@Transactional(readOnly = true)
public class UserQuery {
    @Autowired
    private UserDBRepository userDBRepository;
    @Autowired
    private OrganizationDBRepository organizationDBRepository;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MedicalUserCommitConvert medicalUserCommitConvert;

    public UserVO searchUser(String uname){
        UserEntity userEntity = userDBRepository.findFirstByUnameAndDelFalse(uname);
        if(userEntity == null){
            return null;
        }
        return userMapper.transformToVO(userEntity);
    }

    public UserVO searchUser(OperatorInfo operatorInfo){
        UserEntity userEntity = userDBRepository.findFirstByUnameAndDelFalse(operatorInfo.getOperator());
        if(userEntity == null){
            return null;
        }
        UserVO userVO = userMapper.transformToVO(userEntity);
        //查询登陆用户当前登陆的机构
        OrganizationEntity organizationEntity = organizationDBRepository
                .findFirstByInstitutionNumberAndDelFalse(operatorInfo.getInstitutionNumber());
        userVO.setHisInstitutionNumber(organizationEntity.getHisInstitutionNumber());
        userVO.setInstitutionName(organizationEntity.getInstitutionName());
        userVO.setInstitutionNumber(organizationEntity.getInstitutionNumber());
        return userVO;
    }

    public PageData<UserVO> searchUsersOfConditions(UserCondition userCondition, OperatorInfo operatorInfo){
        Specification<UserEntity> specification = new Specification<UserEntity>() {
            @Override
            public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if(!StringUtils.isEmpty(userCondition.getName())){
                    Predicate predicate = criteriaBuilder.equal(root.get("uname"), userCondition.getName());
                    Predicate predicate1 = criteriaBuilder.like(root.get("userName"), userCondition.getName()+"%");
                    predicateList.add(criteriaBuilder.or(predicate, predicate1));
                }
                if(!StringUtils.isEmpty(userCondition.getInstitutionNumber())){
                    Predicate predicate = criteriaBuilder.equal(root.get("institutionNumber"), userCondition.getInstitutionNumber());
                    predicateList.add(predicate);
                }else{
                    Predicate predicate = criteriaBuilder.equal(root.get("institutionNumber"), operatorInfo.getInstitutionNumber());
                    predicateList.add(predicate);
                }
                if(userCondition.getUserType() != null){
                    Predicate predicate = criteriaBuilder.equal(root.get("userType"), userCondition.getUserType());
                    predicateList.add(predicate);
                }


                Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                predicateList.add(predicate);

                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };

        Pageable pageable = PageRequest.of(userCondition.getCurrPageNo()-1, userCondition.getLimit(), Sort.by(Sort.Order.desc("lastUpdateTime")));
        Page<UserEntity> userPage = userDBRepository.findAll(specification, pageable);

        if(userPage.isEmpty()){
            return new PageData<>(0L, userCondition.getCurrPageNo(), null);
        }
        List<UserVO> userVOS = userPage.stream().map(entity -> {
            UserVO userVO = userMapper.transformToVO(entity);
            userVO.setPassword(null);
            return userVO;
        }).collect(Collectors.toList());
        return new PageData<>(userPage.getTotalElements(), userCondition.getCurrPageNo(), userVOS);
    }

    public List<UserDTO> searchUserOfOrgan(String organNumber){
        List<UserEntity> userEntities = userDBRepository.findAllByInstitutionNumberAndDelFalseAndDisabledFalse(organNumber);
        if(userEntities == null || userEntities.isEmpty()){
            return null;
        }
        return userEntities.stream().map(userEntity -> {
            UserDTO userDTO = userMapper.transformToDTO(userEntity);
            userDTO.setPassword(null);
            return userDTO;
        }).collect(Collectors.toList());
    }

    /**
     * 查询未分配的用户信息(医生,销售)
     * @return
     */
    public List<UserDTO> searchUnallocatedUsers(String institutionNumber){
        List<String> unames = medicalUserCommitConvert.searchAllocationUsers(institutionNumber);
        List<UserEntity> userEntities = null;
        if(CollectionUtils.isEmpty(unames)){
            userEntities = userDBRepository.findAllByInstitutionNumberAndDelFalseAndDisabledFalse(institutionNumber);
        }else{
            userEntities = userDBRepository.findAllByInstitutionNumberAndUnameNotInAndDelFalseAndDisabledFalse(institutionNumber, unames);
        }
        if(CollectionUtils.isEmpty(userEntities)){
            return null;
        }
        return userEntities.stream().map(userEntity -> {
                UserDTO userDTO = userMapper.transformToDTO(userEntity);
                userDTO.setPassword(null);
                return userDTO;
            }).collect(Collectors.toList());
    }

}
